package com.aruba.attendance.ui.widget.datepicker

import androidx.compose.animation.Animatable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch

/**
 * 选择时间（小时：分）的选择器
 * Created by aruba on 2023/2/8.
 */
@Composable
fun DataHourTimePicker(
    hours: ArrayList<String>,
    minutes: ArrayList<String>,
    targetHourIndex: MutableState<Int>,
    targetMinuteIndex: MutableState<Int>,
    textStyle: TextStyle = MaterialTheme.typography.displaySmall,
    initAnimateScroll: Boolean = false,
    timeSelect: ((selectHourIndex: Int, selectMinuteIndex: Int) -> Unit)? = null
) {
    val itemHeight = textStyle.lineHeight.value.dp

    CompositionLocalProvider(
        LocalTextStyle provides textStyle
    ) {
        Row(
            modifier = Modifier.wrapContentWidth(),
            verticalAlignment = Alignment.CenterVertically
        ) {
            DatePickerColumn(
                showList = hours,
                targetIndex = targetHourIndex,
                itemHeight = itemHeight,
                initAnimateScroll = initAnimateScroll
            ) { selectHourIndex ->
                // 更新选中小时
                targetHourIndex.value = selectHourIndex
                // 回调给外部
                timeSelect?.invoke(targetHourIndex.value, targetMinuteIndex.value)
            }

            Text(":", modifier = Modifier.padding(start = 10.dp, end = 10.dp))

            DatePickerColumn(
                showList = minutes,
                targetIndex = targetMinuteIndex,
                itemHeight = itemHeight,
                initAnimateScroll = initAnimateScroll
            ) { selectMinuteIndex ->
                // 更新选中小时
                targetMinuteIndex.value = selectMinuteIndex
                // 回调给外部
                timeSelect?.invoke(targetHourIndex.value, targetMinuteIndex.value)
            }
        }
    }
}

/**
 * 年月日选择器
 */
@Composable
fun DatePicker(
    years: ArrayList<String>,
    months: ArrayList<String>,
    days: ArrayList<String>,
    targetYearIndex: MutableState<Int>,
    targetMonthIndex: MutableState<Int>,
    targetDayIndex: MutableState<Int>,
    monthListState: DateListState,
    dayListState: DateListState,
    textStyle: TextStyle = MaterialTheme.typography.titleLarge,
    initAnimateScroll: Boolean = false,
    timeSelect: ((selectYearIndex: Int, selectMonthIndex: Int) -> Unit)? = null
) {
    val itemHeight = (textStyle.lineHeight.value * 1.5).dp

    CompositionLocalProvider(
        LocalTextStyle provides textStyle
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceAround
        ) {
            DatePickerColumn(
                years,
                targetYearIndex,
                itemHeight,
                initAnimateScroll
            ) { selectYearIndex ->
                targetYearIndex.value = selectYearIndex
                timeSelect?.invoke(targetYearIndex.value, targetMonthIndex.value)
            }

            DatePickerColumn(
                months,
                targetMonthIndex,
                itemHeight,
                initAnimateScroll,
                dateListState = monthListState
            ) { selectMonthIndex ->
                targetMonthIndex.value = selectMonthIndex
                timeSelect?.invoke(targetYearIndex.value, targetMonthIndex.value)
            }

            DatePickerColumn(
                days,
                targetDayIndex,
                itemHeight,
                initAnimateScroll,
                dateListState = dayListState
            ) { selectDayIndex ->
                targetDayIndex.value = selectDayIndex
            }
        }
    }
}

/**
 * 竖向滚动选择控件
 */
@Composable
fun DatePickerColumn(
    showList: List<String>,
    targetIndex: MutableState<Int> = remember { mutableStateOf(0) },
    itemHeight: Dp,
    initAnimateScroll: Boolean = false,
    dateListState: DateListState = rememberSelectDateState(),
    focusColor: Color = MaterialTheme.colorScheme.primary,
    normalColor: Color = Color(0xFFC5C7CF).copy(alpha = 0.5f),
    textStyle: TextStyle = LocalTextStyle.current,
    selectCallback: (selectIndex: Int) -> Unit
) {
    require(showList.isNotEmpty())

    val coroutineScope = rememberCoroutineScope()
    var currentIndex by remember { mutableStateOf(0) }
    val itemHeightPx = with(LocalDensity.current) { itemHeight.roundToPx() }

    val listState = dateListState.lazyListState
    // 首次进来滚动到选中的item为中心
    LaunchedEffect(Unit) {
        if (initAnimateScroll) {
            listState.animateScrollToItem(targetIndex.value + showList.size * 100 - 1)
        } else {
            listState.scrollToItem(targetIndex.value + showList.size * 1000 - 1)
        }
    }

    LazyColumn(
        state = listState,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.height(itemHeight * 3)
    ) {
        items(Int.MAX_VALUE) { index ->
            val indexMod = index % showList.size
            val value = showList[indexMod]

            val animColor = remember { Animatable(normalColor) }
            if (dateListState.scrollAnime.value) {
                LaunchedEffect(targetIndex.value, listState.isScrollInProgress) {
                    if (listState.isScrollInProgress) {
                        animColor.animateTo(normalColor)
                    } else {
                        animColor.animateTo(if (targetIndex.value == indexMod) focusColor else normalColor)
                    }
                }
            }
            Box(
                modifier = Modifier.height(itemHeight),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    text = value,
                    style = textStyle,
                    color = if (dateListState.scrollAnime.value) animColor.value else if (targetIndex.value == indexMod) focusColor else normalColor
                )
            }
        }
    }

    if (listState.isScrollInProgress) {
        DisposableEffect(Unit) {
            // onDispose 将在停止滑动时触发
            onDispose {
                dateListState.scrollAnime.value = true
                if (currentIndex != listState.firstVisibleItemIndex || listState.firstVisibleItemScrollOffset != 0) {// 防止列表一直处于滚动状态
                    //	滑动结束时调用回调函数，并自动对齐
                    coroutineScope.launch {
                        // 根据第一个可见item是否滑动超过半个高度距离来选择是否滚动到下一个item
                        val ratio =
                            if (listState.firstVisibleItemScrollOffset > itemHeightPx / 2) 1 else 0
                        val preCurrentIndex = currentIndex
                        currentIndex = listState.firstVisibleItemIndex + ratio
                        listState.animateScrollToItem(currentIndex)
                        if (preCurrentIndex != currentIndex)
                            selectCallback((currentIndex + 1) % showList.size)
                    }
                }
            }
        }
    }
}